﻿using App.Dal;
using App.Untiys;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace App.Desk
{
    internal static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {
                //设置应用程序处理异常方式：ThreadException处理
                Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                //处理UI线程异常
                Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
                //处理非UI线程异常
                AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
                var aProcessName = Process.GetCurrentProcess().ProcessName.Replace(".vshost", "");
                if ((Process.GetProcessesByName(aProcessName)).GetUpperBound(0) > 0)
                {
                    MessageBox.Show(@"系统已经在运行中，如果要重新启动，请从进程中关闭...", @"系统警告", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                }
                else
                {
                    if (Config.InitializationDataBase == 1)
                        ConfigServices.InitializationDataBase();
                    //清除十五之前的数据
                    ConfigServices.ClearErrors(DateTime.Now.AddDays(15));
                    #region 应用程序的主入口点
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    //Application.Run(new FCustomMain());
                    //Application.Run(new UI_Operate.frmUploadWl());
                    //Application.Run(new UI_Query.frmSamplingPosInfo());
                    //Application.Run(new Monitor.frmPail());
                    //Application.Run(new UI_Sys.frmLog());
                    AppSingle.Run(new FrmLogin(), new FCustomMain());
                    #endregion
                }
            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("****************************异常文本(Application_ThreadException)****************************");
                sb.AppendLine("【出现时间】：" + DateTime.Now.ToString());
                sb.AppendLine("【异常类型】：" + ex.GetType().Name);
                sb.AppendLine("【异常信息】：" + ex.Message);
                sb.AppendLine("【堆栈调用】：" + ex.StackTrace);
                sb.AppendLine("【异常方法】：" + ex.TargetSite);
                sb.AppendLine("***************************************************************");
                MessageBox.Show(sb.ToString(), "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("****************************异常文本(Application_ThreadException)****************************");
            sb.AppendLine("【出现时间】：" + DateTime.Now.ToString());
            if (e.Exception != null)
            {
                sb.AppendLine("【异常类型】：" + e.Exception.GetType().Name);
                sb.AppendLine("【异常信息】：" + e.Exception.Message);
                sb.AppendLine("【堆栈调用】：" + e.Exception.StackTrace);
                sb.AppendLine("【异常方法】：" + e.Exception.TargetSite);
            }
            else
                sb.AppendLine("【未处理异常】：" + e.ToString());
            sb.AppendLine("***************************************************************");
            LogHelper.DoWriteLogTypeSubitem(LogType.Error, LogSubitem.System, sb.ToString());
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("****************************异常文本(CurrentDomain_UnhandledException)****************************");
            sb.AppendLine("【出现时间】：" + DateTime.Now.ToString());
            if (e.ExceptionObject != null)
            {
                Exception ex = (Exception)e.ExceptionObject;
                sb.AppendLine("【异常类型】：" + ex.GetType().Name);
                sb.AppendLine("【异常信息】：" + ex.Message);
                sb.AppendLine("【堆栈调用】：" + ex.StackTrace);
                sb.AppendLine("【异常方法】：" + ex.TargetSite);
            }
            else
                sb.AppendLine("【未处理异常】：" + e.ToString());
            sb.AppendLine("***************************************************************");
            LogHelper.DoWriteLogTypeSubitem(LogType.Error, LogSubitem.System, sb.ToString());
        }

    }

    #region 进程单件类
    /// <summary>
    /// 进程单件类(实现程序只运行一个实例)
    /// </summary>
    internal sealed class AppSingle
    {
        /// <summary>
        /// 设置窗口的显示状态
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="cmdShow"></param>
        /// <returns></returns>
        [DllImport("User32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);

        /// <summary>
        /// 将已经运行的进程的窗口设置到前台，并且激活该窗口
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        [DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        /// <summary>
        /// 判断指定窗体是否已经最小化
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        private static extern bool IsIconic(IntPtr hWnd);

        /// <summary>
        /// 实现单态实例的互斥量
        /// </summary>
        private static Mutex _appMutex = null;

        /// <summary>
        /// 启动程序
        /// </summary>
        /// <param name="splashForm">程序欢迎窗口</param>
        /// <param name="mainForm">程序主窗口</param>
        public static void Run(Form splashForm, Form mainForm)
        {
            System.Diagnostics.Debug.Assert(mainForm != null);

            if (CreateMutex())
            {
                Application.ApplicationExit += new EventHandler(OnAppExit);

                //欢迎窗口
                if (splashForm != null)
                {
                    if (splashForm.ShowDialog() == DialogResult.OK)
                    {
                        splashForm.Dispose();
                        //主窗口
                        Application.Run(mainForm);
                    }
                }
                else
                {
                    //主窗口
                    Application.Run(mainForm);
                }
            }
            else
            {
                MessageBox.Show("程序已启动！", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                Process prcInstance = GetRunningProcessInstance();
                if (prcInstance != null)
                {
                    ShowRunningProcessInstance(prcInstance);
                }
            }
        }

        /// <summary>   
        /// 获取已运行本程序的进程   
        /// </summary>   
        /// <returns></returns>   
        private static Process GetRunningProcessInstance()
        {
            Process current = Process.GetCurrentProcess();
            Process[] processes = Process.GetProcessesByName(current.ProcessName);
            foreach (Process process in processes)
            {
                if (process.Id != current.Id
                    && Assembly.GetExecutingAssembly().Location.Replace("/", "\\")
                        == current.MainModule.FileName)
                {
                    return process;
                }
            }
            return null;
        }

        /// <summary>   
        /// 将指定进程的的窗口设置到前台，并且激活该窗口程序窗口
        /// </summary>   
        /// <param   name="instance"></param>   
        private static void ShowRunningProcessInstance(Process proc)
        {
            if (proc == null)
            {
                return;
            }

            int SW_SHOWNA = 8;//以窗口的当前状态显示窗口并激活窗口
            int SW_RESTORE = 9;//如果窗口已经最小化或最大化，以恢复到原来的尺寸和位置显示并激活窗口
            int showType = SW_SHOWNA;
            if (IsIconic(proc.MainWindowHandle))
            {
                showType = SW_RESTORE;
            }
            ShowWindowAsync(proc.MainWindowHandle, showType);

            //将已经运行的进程的窗口设置到前台，并且激活该窗口
            SetForegroundWindow(proc.MainWindowHandle);
        }

        /// <summary>
        /// 创建互斥对象
        /// </summary>
        /// <returns></returns>
        private static bool CreateMutex()
        {
            _appMutex = new Mutex(false, "采样上位机");
            return _appMutex.WaitOne(TimeSpan.Zero, false);
        }

        /// <summary>
        /// 释放互斥对象
        /// </summary>
        private static void ReleaseMutex()
        {
            if (_appMutex != null)
            {
                _appMutex.ReleaseMutex();
                _appMutex.Close();
            }
        }

        /// <summary>
        /// 程序退出之间的事件，用来删除互斥量
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private static void OnAppExit(object sender, EventArgs args)
        {
            ReleaseMutex();
        }
    }
    #endregion
}
